package core

import (
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"

	"github.com/hirochachacha/go-smb2"
)

// Config 是用于存储配置的结构体
type Config struct {
	User           string `json:"user"`
	Password       string `json:"password"`
	Domain         string `json:"domain"`
	ServerIP       string `json:"serverIP"`
	ServerPort     int    `json:"serverPort"`
	ShareName      string `json:"shareName"`
	RemoteFilePath string `json:"remoteFilePath"`
	LocalFilePath  string `json:"localFilePath"`
	BufferSize     int    `json:"bufferSize"`
}

func LoadConfig(configFile string) (*Config, error) {
	file, err := os.Open(configFile)
	if err != nil {
		return nil, fmt.Errorf("无法打开配置文件: %v", err)
	}
	defer file.Close()

	var config Config
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&config)
	if err != nil {
		return nil, fmt.Errorf("无法解析配置文件: %v", err)
	}

	return &config, nil
}

func SmbDownload() {
	// 加载配置
	config, err := LoadConfig("config.json")
	if err != nil {
		fmt.Printf("加载配置失败: %v\n", err)
		return
	}

	// 创建 TCP 连接
	tcpConn, err := net.Dial("tcp", fmt.Sprintf("%v:%v", config.ServerIP, config.ServerPort))
	if err != nil {
		fmt.Printf("无法建立TCP链接: %v\n", err)
		return
	}
	defer tcpConn.Close()

	// 创建 SMB 客户端
	smbDialer := &smb2.Dialer{
		Initiator: &smb2.NTLMInitiator{
			User:     config.User,
			Password: config.Password,
			// Domain:   config.Domain,
		},
	}

	// 连接到 SMB 服务器
	session, err := smbDialer.Dial(tcpConn)
	if err != nil {
		fmt.Printf("无法连接到服务器: %v\n", err)
		return
	}
	defer session.Logoff()

	// 打开共享
	share, err := session.Mount(config.ShareName)
	if err != nil {
		fmt.Printf("无法挂载共享: %v\n", err)
		return
	}
	defer share.Umount()

	// 打开远程文件
	remoteFile, err := share.Open(config.RemoteFilePath)
	if err != nil {
		fmt.Printf("无法打开远程文件: %v\n", err)
		return
	}
	defer remoteFile.Close()

	// 获取文件大小
	remoteFileInfo, err := remoteFile.Stat()
	if err != nil {
		fmt.Printf("无法获取远程文件信息: %v\n", err)
		return
	}
	remoteFileSize := remoteFileInfo.Size()

	// 获取本地文件大小以支持断点续传
	localFile, err := os.OpenFile(config.LocalFilePath, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Printf("无法打开本地文件: %v\n", err)
		return
	}
	defer localFile.Close()

	localFileInfo, err := localFile.Stat()
	if err != nil {
		fmt.Printf("无法获取本地文件信息: %v\n", err)
		return
	}
	localFileSize := localFileInfo.Size()

	// 如果本地文件大小小于远程文件大小，则进行断点续传
	if localFileSize < remoteFileSize {
		fmt.Printf("从 %d 字节开始下载...\n", localFileSize)
		_, err = remoteFile.Seek(localFileSize, io.SeekStart)
		if err != nil {
			fmt.Printf("无法定位远程文件位置: %v\n", err)
			return
		}
		_, err = localFile.Seek(localFileSize, io.SeekStart)
		if err != nil {
			fmt.Printf("无法定位本地文件位置: %v\n", err)
			return
		}

		buffer := make([]byte, config.BufferSize)
		for {
			n, err := remoteFile.Read(buffer)
			if err != nil && err != io.EOF {
				fmt.Printf("读取远程文件出错: %v\n", err)
				return
			}
			if n == 0 {
				break
			}

			_, err = localFile.Write(buffer[:n])
			if err != nil {
				fmt.Printf("写入本地文件出错: %v\n", err)
				return
			}
		}
	} else {
		fmt.Println("文件已完整下载")
	}

	fmt.Printf("下载完成: %s\n", config.LocalFilePath)
}
